package com.company.project.util;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

import java.net.URLEncoder;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

/**
 * @Description: 钉钉消息管理
 * @author: wanjun
 */

public class DingManager implements IDingManager
{
    private static final String robotKey = "SECa844162347ae73e0023ae43231251acdeee40a7a86ea20b036b29ed481efbaea";
    private static final String webhookUrl = "https://oapi.dingtalk.com/robot/send?access_token=f2f68b761d3668ba4fdd7d1d882be42fbaf75bded0d7356510d7cc272d7c11d2";

    private static final Logger log = LoggerFactory.getLogger(DingManager.class);

    private static RestTemplate restTemplate = new RestTemplate();

    /**
     * 通知人名单
     */
    private List<String> mobileList = new ArrayList<String>();

    @Override
    public String sendDingMsg(String dingRobotAt,String content)
    {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String  sign = "";
        try {
            sign = calculateHmacSHA256(timestamp, robotKey);
        } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) {
            System.out.println("签名失败");
            throw new RuntimeException(e);
        }
        // 钉钉机器人地址（配置机器人的webhook）
        String dingUrl =webhookUrl + "&timestamp=" + timestamp + "&sign=" + sign;
        if (mobileList.isEmpty())
        {
            //填入手机号，可以具体@到某个人
            if (!Objects.isNull(dingRobotAt))
            {
                String [] all = dingRobotAt.split(";");
                if (all != null)
                {
                    mobileList.addAll(Arrays.asList(all));
                }
            }
        }
        //组装请求内容
        Map<String, Object> reqStr = buildReqStr(content, mobileList.isEmpty(), mobileList);
        return invokeGeneralApi(dingUrl, reqStr);

    }

    @Override
    public String sendDingLink(String dingRobotAt, String link,String title,String text) {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String  sign = "";
        try {
            sign = calculateHmacSHA256(timestamp, robotKey);
        } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) {
            System.out.println("签名失败");
            throw new RuntimeException(e);
        }
        // 钉钉机器人地址（配置机器人的webhook）
        String dingUrl =webhookUrl + "&timestamp=" + timestamp + "&sign=" + sign;
        if (mobileList.isEmpty())
        {
            //填入手机号，可以具体@到某个人
            if (!Objects.isNull(dingRobotAt))
            {
                String [] all = dingRobotAt.split(";");
                if (all != null)
                {
                    mobileList.addAll(Arrays.asList(all));
                }
            }
        }
        //组装请求内容
        Map<String, Object> reqStr = buildReqStrLink(link, mobileList.isEmpty(), mobileList,title,text);
        return invokeGeneralApi(dingUrl, reqStr);
    }


    /**
     * 组装请求报文
     * @param content
     * @return
     */
    private Map<String, Object> buildReqStr(String content, boolean isAtAll, List<String> mobileList) {
        //消息内容
        Map<String, String> contentMap = new HashMap<String, String>();
        contentMap.put("content", content);

        //通知人
        Map<String, Object> atMap = new HashMap<String, Object>();
        //1.是否通知所有人
        atMap.put("isAtAll", isAtAll);
        //2.通知具体人的手机号码列表
        atMap.put("atMobiles", mobileList);

        Map<String, Object> reqMap = new HashMap<String, Object>();
        reqMap.put("msgtype", "text");
        reqMap.put("text", contentMap);
        reqMap.put("at", atMap);

        return reqMap;
    }

    private Map<String, Object> buildReqStrLink(String link, boolean isAtAll, List<String> mobileList,String title,String text) {
        //消息内容
        Map<String, String> contentMap = new HashMap<String, String>();
        contentMap.put("messageUrl", link);
        contentMap.put("title", title);
        contentMap.put("text", text);

        //通知人
        Map<String, Object> atMap = new HashMap<String, Object>();
        //1.是否通知所有人
        atMap.put("isAtAll", isAtAll);
        //2.通知具体人的手机号码列表
        atMap.put("atMobiles", mobileList);

        Map<String, Object> reqMap = new HashMap<String, Object>();
        reqMap.put("msgtype", "link");
        reqMap.put("link", contentMap);
        reqMap.put("at", atMap);

        return reqMap;
    }

    private String invokeGeneralApi(String url, Map<String, Object> params) {
        String body = "";
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(params, headers);
            ResponseEntity<String> entity = restTemplate.postForEntity(url, httpEntity, String.class);
            body = entity.getBody();
            log.info("invokeGeneralApi()>>>[{}]", body);
        } catch (RestClientException e) {
            log.error("API调用错误，接口地址:[{}]，请求参数:[{}]", url, params, e);
        }
        return body;
    }

    private static String calculateHmacSHA256(String message, String secretKey)
            throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {

        String stringToSign = message + "\n" + secretKey;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(secretKey.getBytes("UTF-8"), "HmacSHA256"));
        byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
        String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)),"UTF-8");

        return sign;
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder result = new StringBuilder();
        for (byte b : bytes) {
            result.append(String.format("%02x", b));
        }
        return result.toString();
    }

}

